Class=function(name,base1,classScope){
	var args=[];
	for(var i=0;i<arguments.length;i++){
		args[i]=arguments[i];
	}
	classScope=args.pop();
	var classID=Class.__idcount__++;
	if((args.length>0)&&(typeof args[0]=='string')){
		name=args.shift();
	}else{
		name="anonymous"+classID;
	}
	var bases=args;
	var __class__={__isArray__:false,
		__name__:name,
		__bases__:bases,
		__id__:'@'+classID,
		__str__:function(){
			return "[class %s]".format(this.__name__);
		}
	};
	var baseProtos=[];
	var proto;
	if(bases.length==0){
		proto={};
		proto.__str__=function(){
			return "[%s %s]".format(this.__class__.prototype.__call__===undefined?'object':'callable',this.__class__.__name__);
		};
		__class__.__bases__=[Object];
	}else{
		var baseProto;
		for(var i=0;i<bases.length;i++){
			var baseClass=bases[i];
			baseProtos.push(baseClass.prototype);
			if(baseClass.__createProto__!==undefined){
				baseProto=baseClass.__createProto__(bases);
			}else{
				baseProto=new baseClass(Class);
			}
			__class__.__isArray__=__class__.__isArray__||baseClass.__isArray__;
			if(i==0){
				proto=baseProto;
			}else{
				for(var key in baseProto){
					if(proto[key]===undefined){
						proto[key]=baseProto[key];
					}
				}
			}
			for(var key in baseClass){
				if((key!='prototype')&&(__class__[key]===undefined)){
					__class__[key]=baseClass[key];
				}
			}
		}
	}
	if(proto.__id__===undefined){
		proto.__id__=function(){
			this.__id__='@'+(Class.__idcount__++);
			return this.__id__;
		};
	}
	proto.__class__=__class__;
	if(classScope.length-1>baseProtos.length){
		var privId='__priv__'+__class__.__id__;
		classScope.apply(this,[proto,privId].concat(baseProtos));
	}else{
		classScope.apply(this,[proto].concat(baseProtos));
	}
	proto.toString=proto.__str__;
	if(proto.__call__){
		var NewClass=function(calledBy){
			if(calledBy!==Class){
				var rslt=function(){
					return rslt.__call__.apply(rslt,arguments);
				};
				var proto=arguments.callee.prototype;
				for(var n in proto){
					rslt[n]=proto[n];
				}
				rslt.constructor=proto.__class__;
				rslt.toString=proto.__str__;
				if(rslt.__init__){
					rslt.__init__.apply(rslt,arguments);
				}
				return rslt;
			}
		};
	}else if(__class__.__isArray__){
		var NewClass=function(calledBy){
			if(calledBy!==Class){
				rslt=[];
				var proto=arguments.callee.prototype;
				for(var n in proto){
					rslt[n]=proto[n];
				}
				rslt.constructor=proto.__class__;
				rslt.toString=proto.__str__;
				if(rslt.__init__){
					rslt.__init__.apply(rslt,arguments);
				}else{
					if(arguments.length==1){
						rslt.length=arguments[0];
					}else{
						for(var i=0;i<arguments.length;i++){
							rslt.push(arguments[i]);
						}
					}
				}
				return rslt;
			}
		};
	}else{
		var NewClass=function(calledBy){
				if(calledBy!==Class){
					if(this.__init__){
						this.__init__.apply(this,arguments);
					}
				}
		};
	}
	proto.constructor=NewClass;
	proto.__class__=NewClass;
	NewClass.prototype=proto;
	for(var key in __class__){
		NewClass[key]=__class__[key];
	}
	NewClass.toString=__class__.__str__;
	return NewClass;
};



Class.__idcount__=0;
Class.__str__=Class.toString=function(){return "[object Class]";};
Class.__createProto__=function(){throw "Can't use Class as a base class.";};
Function.__createProto__=function(){throw "Cannot inherit from Function. implement the callable interface instead using YourClass::__call__.";};
Array.__createProto__=function(){var r=[];r.__str__=Array.prototype.toString;return r;};
Array.__isArray__=true;
Array.__str__=Array.toString=function(){return "[class Array]";};
Object.__str__=Object.toString=function(){return "[class Object]";};
Number.__str__=Number.toString=function(){return "[class Number]";};
String.__str__=String.toString=function(){return "[class String]";};
str=String;

repr=function(obj){
	if(obj==null){
		return null;
	}else if(obj.__repr__){
		return obj.__repr__();
	}else{
		switch(typeof obj){
			case "string":
				obj=obj.replace(/\\/g,"\\\\").replace(/\"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r");
			return '"'+obj+'"';
			case "boolean":case "number":
				return ""+obj;
			case "object":
				var out=[];
			if(obj==null){
				return "null";
			}else if(obj instanceof Array){
				for(var i=0;i<obj.length;i++){
					out.push(repr(obj[i]));
				}
				return "["+out.join(",")+"]";
			}else if(obj instanceof Object){
				for(var key in obj){
					out.push(repr(key)+":"+repr(obj[key]));
				}
				return "{"+out.join(",")+"}";
			}
		}
	}
};


id=function(obj,forceId){
	switch(typeof obj.__id__){
		case "undefined":
			if(obj instanceof String||typeof obj=='string'){
				return '$'+obj;
			}else if(obj instanceof Number||typeof obj=='number'){
				return '#'+obj;
			}else if(forceId){
				obj.__id__='@'+(Class.__idcount__++);
				return obj.__id__;
			}else{
				throw new jsolait.Exception('Objec cannot be IDed: %s'.format(obj));
			}
		case "function":
			return obj.__id__();
		default:
		return obj.__id__;
	}
};


bind=function(obj,fn){
	return function(){
		return fn.apply(obj,arguments);
	};
};


isinstance=function(obj,cls){
	if(obj instanceof cls){
		return true;
	}else{
		return issubclass(obj.constructor,cls);
	}
};


issubclass=function(cls,baseclass){
	if(baseclass===Object||cls===baseclass||(cls.prototype instanceof baseclass)){
		return true;
	}else{
		var bases=cls.__bases__;
		if(bases!=null){
			for(var i=0;i<bases.length;i++){
				if(bases[i]===baseclass){
					return true;
				}
			}
			for(var i=0;i<bases.length;i++){
				if(issubclass(bases[i],baseclass)){
					return true;
				}
			}
		}
		return false;
	}
};


Module=function(name,version,moduleScope){
	var newMod=new Module.ModuleClass(name,version,Module.currentURI);
	try{
		moduleScope.call(newMod,newMod);
	}catch(e){
		throw new Module.ModuleScopeExecFailed(newMod,e);
	}
	for(var n in newMod){
		var obj=newMod[n];
		if(typeof obj=='function'){
			obj.__name__=n;
		}
	}
	jsolait.registerModule(newMod);
	return newMod;
};


Module.ModuleClass=Class(function(publ){
	publ.name;
	publ.version;
	publ.__sourceURI__;
	publ.Exception;
	publ.__init__=function(name,version,sourceURI){
		this.name=name;
		this.version=version;
		this.__sourceURI__=sourceURI;
		this.Exception=Class(Module.Exception,function(){});
		this.Exception.prototype.module=this;
	};
	publ.__str__=function(){
		return "[module '%s' version: %s]".format(this.name,(this.version+'').replace(/\$Revision: 1.3 $/,"rev.$1"));
	};
});


Module.toString=function(){
	return "[object Module]";
};


Module.__createProto__=function(){
	throw "Can't use Module as a base class.";
};
Module.Exception=Class("Exception",function(publ){
	publ.__init__=function(msg,trace){
		this.name=this.constructor.__name__;
		this.message=''+msg;
		this.trace=trace;
	};
	publ.__str__=function(){
		return this.toTraceString();
	};
	publ.toTraceString=function(indent){
		indent=indent==null?0:indent;
		var s="[%s] in %s:\n%s".format(this.name,this.module,this.message.indent(4)).indent(indent);
		if(this.trace){
			if(this.trace.toTraceString){
				s+=('\n\nbecause:\n'+this.trace.toTraceString(indent+4));
			}else{
				s+=('\n\nbecause:\n'+this.trace+'\n').indent(indent+4);
			}
		}
		return s;
	};
	publ.name;
	publ.message;
	publ.module="jsolait";
	publ.trace;
});
Module.ModuleScopeExecFailed=Class("ModuleScopeExecFailed",Module.Exception,function(publ,supr){
	publ.__init__=function(module,trace){
		supr.__init__.call(this,"Failed to run the module scope for %s".format(module),trace);
		this.failedModule=module;
	};
	publ.module;
	});


Module("jsolait","1.0",function(mod){
jsolait=mod;
mod.modules={};
mod.knownModuleURIs={"async":"%(baseURI)s/lib/async.js","codecs":"%(baseURI)s/lib/codecs.js","crypto":"%(baseURI)s/lib/crypto.js","dom":"%(baseURI)s/lib/dom.js","forms":"%(baseURI)s/lib/forms.js","iter":"%(baseURI)s/lib/iter.js","jsonrpc":"%(baseURI)s/lib/jsonrpc.js","lang":"%(baseURI)s/lib/lang.js","operators":"%(baseURI)s/lib/operators.js","sets":"%(baseURI)s/lib/sets.js","strings":"%(baseURI)s/lib/strings.js","testing":"%(baseURI)s/lib/testing.js","urllib":"%(baseURI)s/lib/urllib.js","xml":"%(baseURI)s/lib/xml.js","xmlrpc":"%(baseURI)s/lib/xmlrpc.js",".svn":"%(baseURI)s/lib/.svn/","net":"%(baseURI)s/lib/net/"};
mod.moduleSearchURIs=["."];
mod.baseURI="./jsolait";
mod.packagesURI="%(baseURI)s/packages";

var getHTTP=function(){
	var obj;
	try{
		obj=new XMLHttpRequest();
	}catch(e){
		try{
			obj=new ActiveXObject("Msxml2.XMLHTTP.4.0");
		}catch(e){
			try{
				obj=new ActiveXObject("Msxml2.XMLHTTP");
			}catch(e){
				try{
					obj=new ActiveXObject("microsoft.XMLHTTP");
				}catch(e){
					throw new mod.Exception("Unable to get an HTTP request object.");
				}
			}
		}
	}
	return obj;
};

mod.loadURI=function(uri,headers){
	headers=(headers!==undefined)?headers:[];
	try{
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
		}catch(e)
		{ }
		var xmlhttp=getHTTP();
		xmlhttp.open("GET",uri,false);
		for(var i=0;i<headers.length;i++){
			xmlhttp.setRequestHeader(headers[i][0],headers[i][1]);
		}
		xmlhttp.send("");
	}catch(e){
		throw new mod.LoadURIFailed(uri,e);
	}
	if(xmlhttp.status==200||xmlhttp.status==0||xmlhttp.status==null||xmlhttp.status==304){
		var s=new String(xmlhttp.responseText);
		s.__sourceURI__=uri;
		return s;
	}else{
		throw new mod.LoadURIFailed(uri,new mod.Exception("Server did not respond with 200"+xmlhttp.status));
	}
};

mod.LoadURIFailed=Class(mod.Exception,function(publ,priv,supr){
	publ.__init__=function(sourceURI,trace){
		supr.__init__.call(this,"Failed to load file: '%s'".format(sourceURI.indent(2)),trace);
		this.sourceURI=sourceURI;
	};
	publ.sourceURI;
});

mod.__imprt__=function(name) {
	if(mod.modules[name]){
		return mod.modules[name];
	}else
	{
		var src,modPath;
		var searchURIs=[];
		if(mod.knownModuleURIs[name]!=undefined){
			searchURIs.push(mod.knownModuleURIs[name].format(mod));
		}else
		{
			name=name.split('.');
			if(name.length>1){
				if(mod.knownModuleURIs[name[0]]!=undefined){
					var uri=mod.knownModuleURIs[name[0]].format(mod);
					searchURIs.push("%s/%s.js".format(uri,name.slice(1).join('/')));
				}
				searchURIs.push("%s/%s.js".format(mod.packagesURI.format(mod),name.join('/')));
			}
			for(var i=0;i<mod.moduleSearchURIs.length;i++){
				searchURIs.push("%s/%s.js".format(mod.moduleSearchURIs[i].format(mod),name.join("/")));
			}
			name=name.join(".");
		}
		var failedURIs=[];
		var traces=[];
		for(var i=0;i<searchURIs.length;i++){
			try{
				src=mod.loadURI(searchURIs[i]);
				break;
			}catch(e){
				failedURIs.push(e.sourceURI);
				traces.push(e);
			}
		}
		if(src==null)
		{
			throw new mod.ImportFailed(name,failedURIs, traces.join(',\n').indent(2)   );
		} else
		{
			try
			{
				var srcURI=src.__sourceURI__;
				src='Module.currentURI="%s";\n%s\nModule.currentURI=null;\n'.format(src.__sourceURI__.replace(/\\/g,'\\\\'),src);
				var f=new Function("",src);
				f();
			}catch(e)
			{
				throw new mod.ImportFailed(name,[srcURI],e);
			}
			if(mod.modules[name]!=null)
			{
				return mod.modules[name];
			}else
			{
				throw new mod.ImportFailed(name,[srcURI],new mod.Exception("Module did not register itself and cannot be imported. "+name));
			}
		}
	}
};

mod.ImportFailed=Class(mod.Exception,function(publ,supr){
	publ.__init__=function(moduleName,moduleURIs,trace){
		supr.__init__.call(this,"Failed to import module: '%s' from:\n%s".format(moduleName,moduleURIs.join(',\n').indent(2)), trace);
		this.moduleName=moduleName;
		this.moduleURIs=moduleURIs;
	};
	publ.moduleName;
	publ.moduleURIs;
});

imprt=function(name){
	return mod.__imprt__(name);
};

mod.__registerModule__=function(modObj,modName){
	if(modName!='jsolait'){
		return mod.modules[modName]=modObj;
	}
};

mod.registerModule=function(modObj,modName){
	modName=modName===undefined?modObj.name:modName;
	return mod.__registerModule__(modObj,modName);
};

var FormatSpecifier=function(s){
	var s=s.match(/%(\(\w+\)){0,1}([ 0-]){0,1}(\+){0,1}(\d+){0,1}(\.\d+){0,1}(.)/);
	if(s[1]){
		this.key=s[1].slice(1,-1);
	}else{
		this.key=null;
	}
	this.paddingFlag=s[2];
	if(this.paddingFlag==""){
		this.paddingFlag=" ";
	}
	this.signed=(s[3]=="+");
	this.minLength=parseInt(s[4]);
	if(isNaN(this.minLength)){
		this.minLength=0;
	}
	if(s[5]){
		this.percision=parseInt(s[5].slice(1,s[5].length));
	}else{
		this.percision=-1;
	}
	this.type=s[6];
};

var pad=function(s,flag,len){
	if(flag=="-"){
		var c=" ";
	}else{
		var c=''+flag;
	}
	var rslt=c.mul(len-s.length);
	if(flag=="-"){
		rslt=s+rslt;
	}else{
		rslt+=s;
	}
	return rslt;
};

/*Where is this used ?*/
String.prototype.format=function(){
	var sf=this.match(/(%(\(\w+\)){0,1}[ 0-]{0,1}(\+){0,1}(\d+){0,1}(\.\d+){0,1}[dibouxXeEfFgGcrs%])|([^%]+)/g);
	if(sf){
		if(sf.join("")!=this){
			throw new mod.Exception("Unsupported formating string.");
		}
	}else{
		throw new mod.Exception("Unsupported formating string.");
	}
	var rslt="";
	var s;
	var obj;
	var cnt=0;
	var frmt;
	var sign="";
	for(var i=0;i<sf.length;i++){
		s=sf[i];
		if(s=="%%"){
			s="%";
		}else if(s=="%s"){
			if(cnt>=arguments.length){
				throw new mod.Exception("Not enough arguments for format string.");
			}else{
				obj=arguments[cnt];
				cnt++;
			}
			if(obj===null){
				obj="null";
			}else if(obj===undefined){
				obj="undefined";
			}
			s=obj.toString();
		}else if(s.slice(0,1)=="%"){
			frmt=new FormatSpecifier(s);
			if(frmt.key){
				if((typeof arguments[0])=="object"&&arguments.length==1){
					obj=arguments[0][frmt.key];
				}else{
					throw new mod.Exception("Object or associative array expected as formating value.");
				}
			}else{
				if(cnt>=arguments.length){
					throw new mod.Exception("Not enough arguments for format string.");
				}else{
					obj=arguments[cnt];
					cnt++;
				}
			}
			if(frmt.type=="s"){
				if(obj===null){
					obj="null";
				}else if(obj===undefined){
					obj="undefined";
				}
				s=pad(obj.toString(),frmt.paddingFlag,frmt.minLength);
			}else if(frmt.type=="c"){
				if(frmt.paddingFlag=="0"){
					frmt.paddingFlag=" ";
				}
				if(typeof obj=="number"){
					s=pad(String.fromCharCode(obj),frmt.paddingFlag,frmt.minLength);
				}else if(typeof obj=="string"){
					if(obj.length==1){
						s=pad(obj,frmt.paddingFlag,frmt.minLength);
					}else{
						throw new mod.Exception("Character of length 1 required.");
					}
				}else{
					throw new mod.Exception("Character or Byte required.");
				}
			}else if(typeof obj=="number"){
				if(obj<0){
					obj=-obj;
					sign="-";
				}else if(frmt.signed){
					sign="+";
				}else{
					sign="";
				}
				switch(frmt.type){
					case "f":
						case "F":
						if(frmt.percision>-1){
							s=obj.toFixed(frmt.percision).toString();
						}else{
							s=obj.toString();
						}
						break;
					case "E": case "e":
						if(frmt.percision>-1){
							s=obj.toExponential(frmt.percision);
						}else{
							s=obj.toExponential();
						}
						s=s.replace("e",frmt.type);
						break;
					case "b":
						s=obj.toString(2);
						s=pad(s,"0",frmt.percision);
						break;
					case "o":
						s=obj.toString(8);
						s=pad(s,"0",frmt.percision);
						break;
					case "x":
						s=obj.toString(16).toLowerCase();
						s=pad(s,"0",frmt.percision);
						break;
					case "X":
						s=obj.toString(16).toUpperCase();
						s=pad(s,"0",frmt.percision);
						break;
					default:
						s=parseInt(obj).toString();
						s=pad(s,"0",frmt.percision);
						break;
				}
				if(frmt.paddingFlag=="0"){
					s=pad(s,"0",frmt.minLength-sign.length);
				}
				s=sign+s;
				s=pad(s,frmt.paddingFlag,frmt.minLength);
			}else{
				throw new mod.Exception("Number required.");
			}
		}
		rslt+=s;
	}
	return rslt;
};

String.prototype.pad=function(flag,len){
	if(flag=="-"){
		var c=" ";
	}else{
		var c=''+flag;
	}
	var s=c.mul(len-this.length);
	if(flag=="-"){
		s=this+s;
	}else{
		s+=this;
	}
	return s;
};

String.prototype.indent=function(indent){
	var out=[];
	var s=this.split('\n');
	for(var i=0;i<s.length;i++){
		out.push(' '.mul(indent)+s[i]);
	}
	return out.join('\n');
};

String.prototype.mul=function(l){
	l=(l<0)?0:l;
	var a=new Array(l+1);
	return a.join(this);
};
}); // Module jsolait
